#ifndef _C_GEODESY_H_
#define _C_GEODESY_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "basictypes.h"


/*************************************************************************************************/

typedef enum 
{
  GEODESY_REFERENCE_ELLIPSE_WGS84 = 0,                         
  GEODESY_REFERENCE_ELLIPSE_AIRY_1830=1,                       
  GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY=2,                    
  GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL=3,             
  GEODESY_REFERENCE_ELLIPSE_BESSEL_1841=4,                     
  GEODESY_REFERENCE_ELLIPSE_CLARKE_1866=5,                     
  GEODESY_REFERENCE_ELLIPSE_CLARKE_1880=6,                     
  GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830=7,             
  GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA=8,      
  GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE=9,   
  GEODESY_REFERENCE_ELLIPSE_GRS_1980=10,                      
  GEODESY_REFERENCE_ELLIPSE_HELMERT_1906=11,                  
  GEODESY_REFERENCE_ELLIPSE_HOUGH_1960=12,                    
  GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924=13,            
  GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969=14,           
  GEODESY_REFERENCE_ELLIPSE_WGS72=15,                          
  GEODESY_REFERENCE_ELLIPSE_PZ90=16                           

} GEODESY_enumReferenceEllipse;


#define GEODESY_REFERENCE_ELLIPSE_WGS84_A                                (6378137.0)
#define GEODESY_REFERENCE_ELLIPSE_WGS84_F_INV                            (298.257223563)       
#define GEODESY_REFERENCE_ELLIPSE_WGS84_B                                (6356752.31424518)
#define GEODESY_REFERENCE_ELLIPSE_WGS84_E2                               (0.00669437999014132)

#define GEODESY_REFERENCE_ELLIPSE_AIRY_1830_A                            (6377563.396)
#define GEODESY_REFERENCE_ELLIPSE_AIRY_1830_F_INV                        (299.3249647)
#define GEODESY_REFERENCE_ELLIPSE_AIRY_1830_B                            (6356256.9092444)
#define GEODESY_REFERENCE_ELLIPSE_AIRY_1830_E2                           (0.00667053999776051)

#define GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_A                         (6377340.189)
#define GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_F_INV                     (299.3249647)       
#define GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_B                         (356034.44794565)
#define GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_E2                        (0.0066705399977606)

#define GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_A                  (6378160.0)
#define GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_F_INV              (298.25)      
#define GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_B                  (6356774.7191953063)      
#define GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_E2                 (0.0066945418545876)      

#define GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_A                          (6377397.155)
#define GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_F_INV                      (299.1528128)      
#define GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_B                          (6356078.9628181886)
#define GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_E2                         (0.00667437223180205)

#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_A                          (6378206.4)
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_F_INV                      (294.9786982)            
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_B                          (6356583.7999989809)
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_E2                         (0.00676865799760959)

#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_A                          (6378249.145)
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_F_INV                      (293.465)      
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_B                          (6356514.8695497755)
#define GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_E2                         (0.00680351128284912)

#define GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_A                   (6377276.345)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_F_INV               (300.8017)      
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_B                   (6356075.4131402392)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_E2                  (0.00663784663019987)

#define GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_A            (6377298.556)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_F_INV        (300.8017)      
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_B            (6356097.5503008962)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_E2           (0.00663784663019965)

#define GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_A         (6377304.063)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_F_INV     (300.8017)      
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_B         (6356103.0389931547)
#define GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_E2        (0.00663784663019970)

#define GEODESY_REFERENCE_ELLIPSE_GRS_1980_A                             (6378137.0)
#define GEODESY_REFERENCE_ELLIPSE_GRS_1980_F_INV                         (298.257222101)              
#define GEODESY_REFERENCE_ELLIPSE_GRS_1980_B                             (6356752.3141403561)
#define GEODESY_REFERENCE_ELLIPSE_GRS_1980_E2                            (0.00669438002290069)

#define GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_A                         (6378200.0)
#define GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_F_INV                     (298.30)       
#define GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_B                         (6356818.1696278909)
#define GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_E2                        (0.00669342162296610)

#define GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_A                           (6378270.0)
#define GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_F_INV                       (297.00)      
#define GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_B                           (6356794.3434343431)
#define GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_E2                          (0.00672267002233347)

#define GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_A                   (6378388.0)
#define GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_F_INV               (297.00)            
#define GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_B                   (6356911.9461279465)
#define GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_E2                  (0.00672267002233323)

#define GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_A                  (6378160.0)
#define GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_F_INV              (298.25)      
#define GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_B                  (6356774.7191953063)
#define GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_E2                 (0.00669454185458760)

#define GEODESY_REFERENCE_ELLIPSE_WGS72_A                                (6378135.0)
#define GEODESY_REFERENCE_ELLIPSE_WGS72_F_INV                            (298.26)      
#define GEODESY_REFERENCE_ELLIPSE_WGS72_B                                (6356750.5200160937)
#define GEODESY_REFERENCE_ELLIPSE_WGS72_E2                               (0.00669431777826668)

#define GEODESY_REFERENCE_ELLIPSE_PZ90_A                                (6378245.0)
#define GEODESY_REFERENCE_ELLIPSE_PZ90_F_INV                            (298.3)      
#define GEODESY_REFERENCE_ELLIPSE_PZ90_B                                (6356863.01877)
#define GEODESY_REFERENCE_ELLIPSE_PZ90_E2                               (0.00673852541468)
/*************************************************************************************************/



BOOL GEODESY_GetReferenceEllipseParameters( 
  const GEODESY_enumReferenceEllipse ellipse, 
  double* a,      
  double* b,      
  double* f_inv,  
  double* e2      
  );



BOOL GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
  const GEODESY_enumReferenceEllipse  referenceEllipse,  
  const double latitude,   
  const double longitude,  
  const double height,     
  double *x,               
  double *y,               
  double *z                
  );

BOOL GEODESY_ConvertEarthFixedCartesianToGeodeticCurvilinearCoordinates(
  const GEODESY_enumReferenceEllipse  referenceEllipse,  
  const double x,              
  const double y,              
  const double z,              
  double *latitude,            
  double *longitude,           
  double *height               
  );


BOOL GEODESY_ComputeNorthingEastingVertical(
  const GEODESY_enumReferenceEllipse  referenceEllipse,  
  const double referenceLatitude,  
  const double referenceLongitude, 
  const double referenceHeight,    
  const double latitude,           
  const double longitude,          
  const double height,             
  double *northing,                
  double *easting,                 
  double *vertical                 
  );



BOOL GEODESY_ComputePositionDifference(
  const GEODESY_enumReferenceEllipse  referenceEllipse,  
  const double referenceLatitude,  
  const double referenceLongitude, 
  const double referenceHeight,    
  const double latitude,           
  const double longitude,          
  const double height,             
  double *difference_northing,     
  double *difference_easting,      
  double *difference_vertical      
  );
 



BOOL GEODESY_ComputeMeridianRadiusOfCurvature(
  const GEODESY_enumReferenceEllipse  referenceEllipse, 
  const double latitude,  
  double*  M              
  );

BOOL GEODESY_ComputePrimeVerticalRadiusOfCurvature(
  const GEODESY_enumReferenceEllipse  referenceEllipse, 
  const double latitude, 
  double*  N             
  );


BOOL GEODESY_ComputeMeridianArcBetweenTwoLatitudes(
  const GEODESY_enumReferenceEllipse  referenceEllipse, 
  const double referenceLatitude,  
  const double latitude,           
  double*      arc                 
  );


BOOL GEODESY_ComputeParallelArcBetweenTwoLongitudes(
  const GEODESY_enumReferenceEllipse  referenceEllipse, 
  const double referenceLatitude, 
  const double referenceLongitude,
  const double longitude,         
  double*      arc                
  );

BOOL GEODESY_RotateVectorFromLocalGeodeticFrameToEarthFixedFrame(
  const double referenceLatitude, 
  const double referenceLongitude,
  const double dN,                
  const double dE,                
  const double dUp,               
  double* dX,                     
  double* dY,                     
  double* dZ                      
  );

BOOL GEODESY_RotateVectorFromEarthFixedFrameToLocalGeodeticFrame(
  const double referenceLatitude, 
  const double referenceLongitude,
  const double dX,                
  const double dY,                
  const double dZ,                
  double* dN,                     
  double* dE,                     
  double* dUp                     
  );

BOOL GEODESY_ComputeAzimuthAndElevationAnglesBetweenToPointsInTheEarthFixedFrame(
  const GEODESY_enumReferenceEllipse  referenceEllipse, 
  const double fromX, 
  const double fromY, 
  const double fromZ, 
  const double toX,   
  const double toY,   
  const double toZ,   
  double* elevation,  
  double* azimuth     
  );
  
#ifdef __cplusplus
}
#endif


#endif // _C_GEODESY_H_
